// scrcpy 控制消息基类与具体消息封装

export class ControlMessage {
  toBuffer() {
    throw new Error('toBuffer() must be implemented')
  }
}

// 键码事件（SC_CONTROL_MSG_TYPE_INJECT_KEYCODE = 0）
export class KeyCodeControlMessage extends ControlMessage {
  constructor(action, keycode, repeat = 0, metastate = 0) {
    super()
    this.action = action >>> 0 // 0 DOWN, 1 UP
    this.keycode = keycode >>> 0
    this.repeat = repeat >>> 0
    this.metastate = metastate >>> 0
  }

  toBuffer() {
    const buf = new ArrayBuffer(14)
    const dv = new DataView(buf)
    dv.setUint8(0, 0)
    dv.setUint8(1, this.action)
    dv.setUint32(2, this.keycode, false)
    dv.setUint32(6, this.repeat, false)
    dv.setUint32(10, this.metastate, false)
    return buf
  }
}

// 触摸事件（SC_CONTROL_MSG_TYPE_INJECT_TOUCH_EVENT = 2）
export class TouchControlMessage extends ControlMessage {
  constructor(action, pointerId, x, y, width, height, pressure = 1.0, buttons = 0) {
    super()
    this.action = action >>> 0 // 0 DOWN, 1 UP, 2 MOVE, 3 CANCEL
    this.pointerId = (pointerId >>> 0)
    this.x = x >>> 0
    this.y = y >>> 0
    this.width = width >>> 0
    this.height = height >>> 0
    this.pressure = Math.max(0, Math.min(1, pressure))
    this.buttons = buttons >>> 0
  }

  toBuffer() {
    const buf = new ArrayBuffer(1 + 1 + 8 + 4 + 4 + 2 + 2 + 2 + 4)
    const dv = new DataView(buf)
    let o = 0
    dv.setUint8(o, 2); o += 1
    dv.setUint8(o, this.action); o += 1
    // pointerId 8B，高 4B=0，低 4B 为 id
    dv.setUint32(o, 0, false); o += 4
    dv.setUint32(o, this.pointerId >>> 0, false); o += 4
    dv.setUint32(o, this.x >>> 0, false); o += 4
    dv.setUint32(o, this.y >>> 0, false); o += 4
    dv.setUint16(o, this.width & 0xffff, false); o += 2
    dv.setUint16(o, this.height & 0xffff, false); o += 2
    dv.setUint16(o, Math.max(0, Math.min(65535, Math.floor(this.pressure * 65535))), false); o += 2
    dv.setUint32(o, this.buttons >>> 0, false); o += 4
    return buf
  }
}

// 滚动事件（SC_CONTROL_MSG_TYPE_INJECT_SCROLL_EVENT = 3）
export class ScrollControlMessage extends ControlMessage {
  constructor(x, y, width, height, hScroll, vScroll, buttons = 0) {
    super()
    this.x = x >>> 0
    this.y = y >>> 0
    this.width = width >>> 0
    this.height = height >>> 0
    this.hScroll = hScroll | 0 // int32
    this.vScroll = vScroll | 0 // int32
    this.buttons = buttons >>> 0
  }

  toBuffer() {
    const buf = new ArrayBuffer(1 + 4 + 4 + 2 + 2 + 4 + 4 + 4)
    const dv = new DataView(buf)
    let o = 0
    dv.setUint8(o, 3); o += 1
    dv.setUint32(o, this.x >>> 0, false); o += 4
    dv.setUint32(o, this.y >>> 0, false); o += 4
    dv.setUint16(o, this.width & 0xffff, false); o += 2
    dv.setUint16(o, this.height & 0xffff, false); o += 2
    dv.setInt32(o, this.hScroll | 0, false); o += 4
    dv.setInt32(o, this.vScroll | 0, false); o += 4
    dv.setUint32(o, this.buttons >>> 0, false); o += 4
    return buf
  }
}


